<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh-cn">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>在Linux下使用libxml2----从安装到使用 - 蹒跚 - 博客园</title>
<link type="text/css" rel="stylesheet" href="/bundles/blog-common.css?v=VDh8zSH1vx51MDqRT7hK220akQ58FjlaaeGuWBPhfOA1"/>
<link id="MainCss" type="text/css" rel="stylesheet" href="/skins/WebLoad/bundle-WebLoad.css?v=IwxJ-EEtKGB6HmbztdE0pgD5JAO3gNBVU45kpOi7Zew1"/>
<link title="RSS" type="application/rss+xml" rel="alternate" href="http://www.cnblogs.com/shanzhizi/rss"/>
<link title="RSD" type="application/rsd+xml" rel="EditURI" href="http://www.cnblogs.com/shanzhizi/rsd.xml"/>
<link type="application/wlwmanifest+xml" rel="wlwmanifest" href="http://www.cnblogs.com/shanzhizi/wlwmanifest.xml"/>
<script src="http://common.cnblogs.com/script/jquery.js" type="text/javascript"></script>  
<script type="text/javascript">var currentBlogApp = 'shanzhizi', cb_enable_mathjax=false;</script>
<script src="/bundles/blog-common.js?v=Lo_yNgOy3xSX4jFztznlaU-fp0VmAT5VQ5SPZYVI7BE1" type="text/javascript"></script>
</head>
<body>
<a name="top"></a>

<div id="home">
<div id="header">
	<div id="blogTitle">
		
<!--done-->
<div class="title"><a id="Header1_HeaderTitle" class="headermaintitle" href="http://www.cnblogs.com/shanzhizi/">蹒跚</a></div>
<div class="subtitle">蹒跚的博客http://www.cnblogs.com/shanzhizi</div>



		
	</div><!--end: blogTitle 博客的标题和副标题 -->
	<div id="navigator">
		
<ul id="navList">
<li id="nav_sitehome"></li>
<li id="nav_myhome"><a id="MyLinks1_MyHomeLink" class="menu" href="http://www.cnblogs.com/shanzhizi/">首页</a></li>
<li id="nav_q"><a class="menu" href="http://q.cnblogs.com/">博问</a></li>
<li id="nav_ing"><a class="menu" href="http://home.cnblogs.com/ing/">闪存</a></li>
<li id="nav_newpost"></li>
<li id="nav_contact"></li>
<li id="nav_rss"><a id="MyLinks1_Syndication" class="menu" href="http://www.cnblogs.com/shanzhizi/rss">订阅</a>
<!--<a id="MyLinks1_XMLLink" class="aHeaderXML" href="http://www.cnblogs.com/shanzhizi/rss"><img src="http://www.cnblogs.com/images/xml.gif" alt="订阅" /></a>--></li>
<li id="nav_admin"><a id="MyLinks1_Admin" class="menu" rel="nofollow" href="http://i.cnblogs.com/">管理</a></li>
</ul>

		<div class="blogStats">
			
			
<!--done-->
随笔-8&nbsp;
文章-1&nbsp;
评论-2&nbsp;

			
		</div><!--end: blogStats -->
	</div><!--end: navigator 博客导航栏 -->
</div><!--end: header 头部 -->
<div id="main">
	<div id="mainContent">
	<div class="forFlow">
		

<!--done-->
<div id="topics">
	<div class = "post">
		<h1 class = "postTitle">
			<a id="cb_post_title_url" class="postTitle2" href="http://www.cnblogs.com/shanzhizi/archive/2012/07/09/2583739.html">在Linux下使用libxml2----从安装到使用</a>
		</h1>
		<div class="clear"></div>
		<div class="postBody">
			<div id="cnblogs_post_body"><p align="left"><strong>文章来自：<a href="http://blog.csdn.net/shanzhizi/article/details/7726679">http://blog.csdn.net/shanzhizi/article/details/7726679</a></strong></p>
<p align="left"><strong><span>一、下载和安装LIBXML2</span></strong><span><br /></span><span>【方法一】</span></p>
<p align="left"><span><strong>Libxml2</strong></span><span>是个C</span>语言的XML程式库，能简单方便的提供对XML文件的各种操作，并且支持XPATH查询，及部分的支持XSLT转换等功能。<strong>Libxml2</strong>的下载地址是<br /><a href="http://xmlsoft.org/"><span>http://xmlsoft.org/</span></a><br />完全版的库是开源的，并且带有例子程式和说明文件。由于我是在linux下用C语言进行研发的，所以我下载的是libxml2-2.6.20.tar.gz版本的源码包。</p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>具体安装步骤：<br />1</span>、解压：$tar zxvf libxml2-2.6.20.tar.gz<br />2、进入解压后的安装目录：$cd libxml2-2.6.20<br />3、安装三部曲：1）$./configure<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2)$make<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3)$make install<br />安装完毕。</p>
<p align="left"><span>libxml2</span><span>安装中出现的错误</span><span>:</span></p>
<p align="left"><span>cannot remove `libtoolT': No such file or directory</span></p>
<p align="left"><span>解决方法</span><span>:</span></p>
<p align="left"><span>修改</span><span>configure</span><span>文件</span></p>
<p align="left"><span>$ vim configure</span></p>
<p align="left"><span>删除这一行</span><span>: $RM "$cfgfile"&nbsp;</span></p>
<p align="left"><span>重新再运行</span><span>&nbsp;$ ./configure</span></p>
<p align="left"><span>&nbsp;</span></p>
<p align="left">你在安装libxml2的时候，./configure&nbsp; --prefix=/usr/local&nbsp;<br />你在安装好后，需要重新定义：&nbsp;<br />export&nbsp; LD_LIBRARY_PATH=/usr/local/lib&nbsp;<br />export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig&nbsp;<br />具体的位置根据prefix指定的路径定。</p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>【方法二】</span></p>
<p align="left"><span>#sudo apt-get install libxml2</span></p>
<p align="left"><span>#sudo apt-get install libxml2-dev</span></p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>【方法三】</span></p>
<p align="left"><span><strong>libxml2&nbsp;</strong></span><span>安装使用 收藏</span></p>
<p align="left"><span>&nbsp;&nbsp;</span><span>在项目中需要对数据的保存与交换，为了方便期间使用普通文本保存。但对文本解析时，考虑到程序的健壮性就需要处理多种意外情况，比较麻烦，因此对xml</span>产生了点兴趣。xml本身网站上有大把的资料，可以随时参考。</p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>&nbsp;&nbsp;Gnome</span><span>项目提供了一个xml</span>的C解析器:Libxml2。libxml2最新提供了xmlreader接口，使用很方便，不过版本在2.6以上才支持。今天倒腾了一了下，做了下简单测试，在编译自己的小程序上被拌了一下，写文纪念。</p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>&nbsp;&nbsp;</span><span>现在的最新版本是2.6.30</span>，可以到http://ftp.gnome.org/pub/GNOME/sources/libxml2/2.6/&nbsp;下载。</p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>&nbsp;</span><span>安装很简单，三部走。</span></p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>view plaincopy to clipboardprint?</span></p>
<p align="left"><span>01.// install&nbsp;&nbsp;</span></p>
<p align="left"><span>02.#./configure&nbsp;&nbsp;</span></p>
<p align="left"><span>03.#make&nbsp;&nbsp;</span></p>
<p align="left"><span>04.#make install&nbsp;&nbsp;</span></p>
<p align="left"><span>05.//test install&nbsp;&nbsp;</span></p>
<p align="left"><span>06.#make tests&nbsp;&nbsp;</span></p>
<p align="left"><span>07.//uninstall&nbsp;&nbsp;</span></p>
<p align="left"><span>08.#make uninstall&nbsp;</span></p>
<p align="left"><span>// install</span></p>
<p align="left"><span>#./configure</span></p>
<p align="left"><span>#make</span></p>
<p align="left"><span>#make install</span></p>
<p align="left"><span>//test install</span></p>
<p align="left"><span>#make tests</span></p>
<p align="left"><span>//uninstall</span></p>
<p align="left"><span>#make uninstall</span></p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>&nbsp;&nbsp;</span><span>如果不需要特别的定制，在configure</span>阶段可以直接默认。&nbsp;libxml2将默认把头文件与库安装在/usr/local/include/libxml2/libxml目录下。因此可能会让你在第一次编译自己的程序时遇到头文件&ldquo;no such file&rdquo;的错误（比如我自己就这么笨╮(╯▽╰)╭）。</p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>&nbsp;&nbsp;libxml2</span><span>提供了解决方法，它很体贴地在/usr/local/bin</span>目录下为您提供了xml2-config、xmlcatalog、xmllint三个便利的工具（嘀咕下：其实一点都不便利，提前给人说下多好啊，还得害人去查资料）。其中xml2-config在编译时用得到。</p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>&nbsp;&nbsp;xml2-config</span><span>可以。。。自己看下面吧</span></p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>view plaincopy to clipboardprint?</span></p>
<p align="left"><span>01.[root@Amanda ~]# xml2-config&nbsp;&nbsp;&nbsp;</span></p>
<p align="left"><span>02.Usage: xml2-config [OPTION]&nbsp;&nbsp;</span></p>
<p align="left"><span>03.Known values for OPTION are:&nbsp;&nbsp;</span></p>
<p align="left"><span>04.&nbsp;&nbsp;--prefix=DIR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;change libxml prefix [default /usr/local]&nbsp;&nbsp;</span></p>
<p align="left"><span>05.&nbsp;&nbsp;--exec-prefix=DIR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;change libxml exec prefix [default /usr/local]&nbsp;&nbsp;</span></p>
<p align="left"><span>06.&nbsp;&nbsp;--libs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print library linking information&nbsp;&nbsp;</span></p>
<p align="left"><span>07.&nbsp;&nbsp;--cflags&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print pre-processor and compiler flags&nbsp;&nbsp;</span></p>
<p align="left"><span>08.&nbsp;&nbsp;--modules&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module support enabled&nbsp;&nbsp;</span></p>
<p align="left"><span>09.&nbsp;&nbsp;--help&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;display this help and exit&nbsp;&nbsp;</span></p>
<p align="left"><span>10.&nbsp;&nbsp;--version&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;output version information&nbsp;</span></p>
<p align="left"><span>[root@Amanda ~]# xml2-config</span></p>
<p align="left"><span>Usage: xml2-config [OPTION]</span></p>
<p align="left"><span>Known values for OPTION are:</span></p>
<p align="left"><span>&nbsp;&nbsp;--prefix=DIR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;change libxml prefix [default /usr/local]</span></p>
<p align="left"><span>&nbsp;&nbsp;--exec-prefix=DIR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;change libxml exec prefix [default /usr/local]</span></p>
<p align="left"><span>&nbsp;&nbsp;--libs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print library linking information</span></p>
<p align="left"><span>&nbsp;&nbsp;--cflags&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print pre-processor and compiler flags</span></p>
<p align="left"><span>&nbsp;&nbsp;--modules&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module support enabled</span></p>
<p align="left"><span>&nbsp;&nbsp;--help&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;display this help and exit</span></p>
<p align="left"><span>&nbsp;&nbsp;--version&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;output version information</span></p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>这里说到编译时用到的参数: --cflags</span>和--libs，帮助上说明这个为工程编译时提供辅助。它们提供的信息如下：</p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>view plaincopy to clipboardprint?</span></p>
<p align="left"><span>01.[root@Amanda ~]# xml2-config --cflags&nbsp;&nbsp;</span></p>
<p align="left"><span>02.-I/usr/local/include/libxml2&nbsp;&nbsp;</span></p>
<p align="left"><span>03.[root@Amanda ~]# xml2-config --libs&nbsp;&nbsp;</span></p>
<p align="left"><span>04.-L/usr/local/lib -lxml2 -lz -lm&nbsp;</span></p>
<p align="left"><span>[root@Amanda ~]# xml2-config --cflags</span></p>
<p align="left"><span>-I/usr/local/include/libxml2</span></p>
<p align="left"><span>[root@Amanda ~]# xml2-config --libs</span></p>
<p align="left"><span>-L/usr/local/lib -lxml2 -lz -lm</span></p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>所以在编译自己的测试程序时，可以直接使用&nbsp;#gcc -I /usr/local/include/libxml2 -L/usr/local/lib -lxml2 -lz -lm&nbsp;&nbsp;-o test test.c&nbsp;</span>。</p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>或者加入到makefile</span>中，例如：</p>
<p align="left"><span>CFLAGS=`xml2-config --cflags`</span></p>
<p align="left"><span>LIBS=`xml2-config --libs`</span></p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><strong><span>测试程序：</span></strong></p>
<p align="left"><a name="OLE_LINK2"></a><a name="OLE_LINK1"></a><span>#include &lt;stdio.h&gt;</span></p>
<p align="left"><span>#include &lt;libxml/parser.h&gt;</span></p>
<p align="left"><span>#include &lt;libxml/tree.h&gt;</span></p>
<p align="left"><span>int main(int argc, char **argv)</span></p>
<p align="left"><span>{</span></p>
<p align="left"><span>&nbsp;&nbsp;xmlDocPtr doc = NULL;</span></p>
<p align="left"><span>&nbsp;&nbsp;xmlNodePtr root_node = NULL, node = NULL, node1 = NULL;</span></p>
<p align="left"><span>&nbsp;&nbsp;doc = xmlNewDoc(BAD_CAST "1.0");</span></p>
<p align="left"><span>&nbsp;&nbsp;root_node = xmlNewNode(NULL, BAD_CAST "root");</span></p>
<p align="left"><span>&nbsp;&nbsp;xmlDocSetRootElement(doc, root_node);</span></p>
<p align="left"><span>&nbsp;&nbsp;xmlNewChild(root_node, NULL, BAD_CAST "node1",BAD_CAST "content of node1");</span></p>
<p align="left"><span>&nbsp;&nbsp;node=xmlNewChild(root_node, NULL, BAD_CAST "node3",BAD_CAST"node has attributes");</span></p>
<p align="left"><span>&nbsp;&nbsp;xmlNewProp(node, BAD_CAST "attribute", BAD_CAST "yes");</span></p>
<p align="left"><span>&nbsp;&nbsp;node = xmlNewNode(NULL, BAD_CAST "node4");</span></p>
<p align="left"><span>&nbsp;&nbsp;node1 = xmlNewText(BAD_CAST"other way to create content");</span></p>
<p align="left"><span>&nbsp;&nbsp;xmlAddChild(node, node1);</span></p>
<p align="left"><span>&nbsp;&nbsp;xmlAddChild(root_node, node);</span></p>
<p align="left"><span>&nbsp;&nbsp;xmlSaveFormatFileEnc(argc &gt; 1 ? argv[1] : "-", doc, "UTF-8", 1);</span></p>
<p align="left"><span>&nbsp;&nbsp;xmlFreeDoc(doc);</span></p>
<p align="left"><span>&nbsp;&nbsp;xmlCleanupParser();</span></p>
<p align="left"><span>&nbsp;&nbsp;xmlMemoryDump();&nbsp;&nbsp;&nbsp;</span></p>
<p align="left"><span>&nbsp;&nbsp;return(0);</span></p>
<p align="left"><span>}</span></p>
<p>&nbsp;</p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>用下面的命令编译通过。</span></p>
<p align="left"><span>&nbsp;</span></p>
<p align="left"><span>gcc -I /usr/local/include/libxml2&nbsp;&nbsp;-L /usr/local/lib -lxml2 test.c -o test</span></p>
<p align="left"><strong><span>&nbsp;</span></strong></p>
<p align="left"><strong><span>二、Libxml2</span>中的数据类型和函数</strong></p>
<p align="left"><span>一个函数库中可能有几百种数据类型及几千个函数，不过记住大师的话，90%</span>的功能都是由30%的内容提供的。对于<strong>libxml2(<a href="http://blog.csdn.net/shanzhizi">http://blog.csdn.net/shanzhizi</a>)</strong>，我认为搞懂以下的数据类型和函数就足够了。<br />2.1&nbsp;&nbsp;&nbsp;内部字符类型xmlChar<br />xmlChar是Libxml2中的字符类型，库中所有字符、字符串都是基于这个数据类型。事实上他的定义是：xmlstring.h<br />typedef unsigned char xmlChar;<br />使用unsigned char作为内部字符格式是考虑到他能非常好适应UTF-8编码，而UTF-8编码正是libxml2的内部编码，其他格式的编码要转换为这个编码才能在libxml2中使用。<br />还经常能看到使用xmlChar*作为字符串类型，非常多函数会返回一个动态分配内存的xmlChar*变量，使用这样的函数时记得要手动删除内存。<br />2.2&nbsp;&nbsp; xmlChar相关函数<br />如同标准c中的char类型相同，xmlChar也有动态内存分配、字符串操作等相关函数。例如xmlMalloc是动态分配内存的函数；xmlFree是配套的释放内存函数；xmlStrcmp是字符串比较函数等等。<br />基本上xmlChar字符串相关函数都在xmlstring.h中定义；而动态内存分配函数在xmlmemory.h中定义。<br />2.3&nbsp;&nbsp; xmlChar*和其他类型之间的转换<br />另外要注意，因为总是要在xmlChar*和char*之间进行类型转换，所以定义了一个宏BAD_CAST，其定义如下：xmlstring.h<br />#define BAD_CAST (xmlChar *)<br />原则上来说，unsigned char和char之间进行强制类型转换是没有问题的。<br />2.4&nbsp;&nbsp;&nbsp;文件类型xmlDoc、指针xmlDocPtr<br />xmlDoc是个struct，保存了一个xml的相关信息，例如文件名、文件类型、子节点等等；xmlDocPtr等于xmlDoc*，他搞成这个样子总让人以为是智能指针，其实不是，要手动删除的。<br />xmlNewDoc函数创建一个新的文件指针。<br />xmlParseFile函数以默认方式读入一个UTF-8格式的文件，并返回文件指针。<br />xmlReadFile函数读入一个带有某种编码的xml文件，并返回文件指针；细节见libxml2参考手册。<br />xmlFreeDoc释放文件指针。特别注意，当你调用xmlFreeDoc时，该文件所有包含的节点内存都被释放，所以一般来说不必手动调用xmlFreeNode或xmlFreeNodeList来释放动态分配的节点内存，除非你把该节点从文件中移除了。一般来说，一个文件中所有节点都应该动态分配，然后加入文件，最后调用xmlFreeDoc一次释放所有节点申请的动态内存，这也是为什么我们非常少看见xmlNodeFree的原因。<br />xmlSaveFile将文件以默认方式存入一个文件。<br />xmlSaveFormatFileEnc可将文件以某种编码/格式存入一个文件中。<br />2.5&nbsp;&nbsp;&nbsp;节点类型xmlNode、指针xmlNodePtr<br />节点应该是xml中最重要的元素了，xmlNode代表了xml文件中的一个节点，实现为一个struct，内容非常丰富：tree.h<br />typedef struct _xmlNode xmlNode;<br />typedef xmlNode *xmlNodePtr;<br />struct _xmlNode {<br />&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *_private;/* application data */<br />&nbsp;&nbsp;&nbsp; xmlElementType&nbsp;&nbsp; type;&nbsp;&nbsp; /* type number, must be second ! */<br />&nbsp;&nbsp;&nbsp; const xmlChar&nbsp;&nbsp; *name;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* the name of the node, or the entity */<br />&nbsp;&nbsp;&nbsp; struct _xmlNode *children; /* parent-&gt;childs link */<br />&nbsp;&nbsp;&nbsp; struct _xmlNode *last;&nbsp;&nbsp; /* last child link */<br />&nbsp;&nbsp;&nbsp; struct _xmlNode *parent;/* child-&gt;parent link */<br />&nbsp;&nbsp;&nbsp; struct _xmlNode *next;&nbsp;&nbsp; /* next sibling link */<br />&nbsp;&nbsp;&nbsp; struct _xmlNode *prev;&nbsp;&nbsp; /* previous sibling link */<br />&nbsp;&nbsp;&nbsp; struct _xmlDoc *doc;/* the containing document */<br />&nbsp;&nbsp;&nbsp; /* End of common part */<br />&nbsp;&nbsp;&nbsp; xmlNs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *ns;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* pointer to the associated namespace */<br />&nbsp;&nbsp;&nbsp; xmlChar&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *content;&nbsp;&nbsp; /* the content */<br />&nbsp;&nbsp;&nbsp; struct _xmlAttr *properties;/* properties list */<br />&nbsp;&nbsp;&nbsp; xmlNs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *nsDef;&nbsp;&nbsp;&nbsp;&nbsp; /* namespace definitions on this node */<br />&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *psvi;/* for type/PSVI informations */<br />&nbsp;&nbsp;&nbsp; unsigned short&nbsp;&nbsp; line;&nbsp;&nbsp; /* line number */<br />&nbsp;&nbsp;&nbsp; unsigned short&nbsp;&nbsp; extra; /* extra data for XPath/XSLT */<br />};<br />能看到，节点之间是以链表和树两种方式同时组织起来的，next和prev指针能组成链表，而parent和children能组织为树。同时更有以下重要元素：<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;节点中的文字内容：content；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;节点所属文件：doc；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;节点名字：name；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;节点的namespace：ns；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;节点属性列表：properties；<br />Xml文件的操作其根本原理就是在节点之间移动、查询节点的各项信息，并进行增加、删除、修改的操作。<br />xmlDocSetRootElement函数能将一个节点设置为某个文件的根节点，这是将文件和节点连接起来的重要手段，当有了根结点以后，所有子节点就能依次连接上根节点，从而组织成为一个xml树。<br />2.6&nbsp;&nbsp;&nbsp;节点集合类型xmlNodeSet、指针xmlNodeSetPtr<br />节点集合代表一个由节点组成的变量，节点集合只作为Xpath的查询结果而出现（XPATH的介绍见后面），因此被定义在xpath.h中，其定义如下：<br />/*<br />* A node-set (an unordered collection of nodes without duplicates).<br />*/<br />typedef struct _xmlNodeSet xmlNodeSet;<br />typedef xmlNodeSet *xmlNodeSetPtr;<br />struct _xmlNodeSet {<br />&nbsp;&nbsp;&nbsp; int nodeNr;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* number of nodes in the set */<br />&nbsp;&nbsp;&nbsp; int nodeMax;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* size of the array as allocated */<br />&nbsp;&nbsp;&nbsp; xmlNodePtr *nodeTab;/* array of nodes in no particular order */<br />&nbsp;&nbsp;&nbsp; /* @@ with_ns to check wether namespace nodes should be looked at @@ */<br />};<br />能看出，节点集合有三个成员，分别是节点集合的节点数、最大可容纳的节点数，及节点数组头指针。对节点集合中各个节点的访问方式非常简单，如下：<br />xmlNodeSetPtr nodeset = XPATH查询结果;<br />for (int i = 0; i nodeNr; i++)&nbsp;<br />{<br />nodeset-&gt;nodeTab;<br />}<br />注意，libxml2是个c函数库，因此其函数和数据类型都使用c语言的方式来处理。如果是c++，我想我宁愿用STL中的vector来表示一个节点集合更好，而且没有内存泄漏或溢出的担忧。<br />3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;简单xml操作例子<br />了解以上基本知识之后，就能进行一些简单的xml操作了。当然，还没有涉及到内码转换（使得xml中能处理中文）、xpath等较复杂的操作。<br />3.1&nbsp;&nbsp;&nbsp;创建xml文件<br />有了上面的基础，创建一个xml文件显得非常简单，其流程如下：<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用xmlNewDoc函数创建一个文件指针doc；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用xmlNewNode函数创建一个节点指针root_node；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用xmlDocSetRootElement将root_node设置为doc的根结点；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;给root_node添加一系列的子节点，并设置子节点的内容和属性；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用xmlSaveFile将xml文件存入文件；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用xmlFreeDoc函数关闭文件指针，并清除本文件中所有节点动态申请的内存。<br />注意，有多种方式能添加子节点：第一是用xmlNewTextChild直接添加一个文本子节点；第二是先创建新节点，然后用xmlAddChild将新节点加入上层节点。<br />原始码文件是CreateXmlFile.cpp，如下：<br />/********************************************************************<br />&nbsp;&nbsp;&nbsp; created:&nbsp;&nbsp; 2007/11/09<br />&nbsp;&nbsp;&nbsp; created:&nbsp;&nbsp; 9:11:2007&nbsp;&nbsp; 15:34<br />&nbsp;&nbsp;&nbsp; filename: CreateXmlFile.cpp<br />&nbsp;&nbsp;&nbsp; author:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Wang xuebin&nbsp;<br />&nbsp;&nbsp;&nbsp; depend:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; libxml2.lib&nbsp;<br />&nbsp;&nbsp;&nbsp; build:&nbsp;&nbsp;&nbsp;&nbsp; nmake TARGET_NAME=CreateXmlFile<br />&nbsp;&nbsp;&nbsp; purpose:&nbsp;&nbsp;&nbsp;创建一个xml文件<br />*********************************************************************/<br />#include&nbsp;<br />#include&nbsp;<br />#include&nbsp;<br />#include&nbsp;<br />int main()<br />{<br />&nbsp;&nbsp;&nbsp; //定义文件和节点指针<br />&nbsp;&nbsp;&nbsp; xmlDocPtr doc = xmlNewDoc(BAD_CAST"1.0");<br />&nbsp;&nbsp;&nbsp; xmlNodePtr root_node = xmlNewNode(NULL,BAD_CAST"root");<br />&nbsp;&nbsp;&nbsp; //设置根节点<br />&nbsp;&nbsp;&nbsp; xmlDocSetRootElement(doc,root_node);<br />&nbsp;&nbsp;&nbsp; //在根节点中直接创建节点<br />&nbsp;&nbsp;&nbsp; xmlNewTextChild(root_node, NULL, BAD_CAST "newNode1", BAD_CAST "newNode1 content");<br />&nbsp;&nbsp;&nbsp; xmlNewTextChild(root_node, NULL, BAD_CAST "newNode2", BAD_CAST "newNode2 content");<br />&nbsp;&nbsp;&nbsp; xmlNewTextChild(root_node, NULL, BAD_CAST "newNode3", BAD_CAST "newNode3 content");<br />&nbsp;&nbsp;&nbsp; //创建一个节点，设置其内容和属性，然后加入根结点<br />&nbsp;&nbsp;&nbsp; xmlNodePtr node = xmlNewNode(NULL,BAD_CAST"node2");<br />&nbsp;&nbsp;&nbsp; xmlNodePtr content = xmlNewText(BAD_CAST"NODE CONTENT");<br />&nbsp;&nbsp;&nbsp; xmlAddChild(root_node,node);<br />&nbsp;&nbsp;&nbsp; xmlAddChild(node,content);<br />&nbsp;&nbsp;&nbsp; xmlNewProp(node,BAD_CAST"attribute",BAD_CAST "yes");<br />&nbsp;&nbsp;&nbsp; //创建一个儿子和孙子节点<br />&nbsp;&nbsp;&nbsp; node = xmlNewNode(NULL, BAD_CAST "son");<br />&nbsp;&nbsp;&nbsp; xmlAddChild(root_node,node);<br />&nbsp;&nbsp;&nbsp; xmlNodePtr grandson = xmlNewNode(NULL, BAD_CAST "grandson");<br />&nbsp;&nbsp;&nbsp; xmlAddChild(node,grandson);<br />&nbsp;&nbsp;&nbsp; xmlAddChild(grandson, xmlNewText(BAD_CAST "This is a grandson node"));<br />&nbsp;&nbsp;&nbsp; //存储xml文件<br />&nbsp;&nbsp;&nbsp; int nRel = xmlSaveFile("CreatedXml.xml",doc);<br />&nbsp;&nbsp;&nbsp; if (nRel != -1)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout一个xml文件被创建,写入"个字节"&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; //释放文件内节点动态申请的内存<br />&nbsp;&nbsp;&nbsp; xmlFreeDoc(doc);<br />&nbsp;&nbsp;&nbsp; return 1;<br />}<br />编译链接命令如下：<br />nmake TARGET_NAME=CreateXmlFile<br />然后执行可执行文件CreateXmlFile.exe，会生成一个xml文件CreatedXml.xml，打开后如下所示：<br />root&gt;<br />&nbsp;&nbsp;&nbsp; newNode1&gt;newNode1 contentnewNode1&gt;<br />&nbsp;&nbsp;&nbsp; newNode2&gt;newNode2 contentnewNode2&gt;<br />&nbsp;&nbsp;&nbsp; newNode3&gt;newNode3 contentnewNode3&gt;<br />&nbsp;&nbsp;&nbsp; node2 attribute="yes"&gt;NODE CONTENTnode2&gt;<br />&nbsp;&nbsp;&nbsp; son&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; grandson&gt;This is a grandson nodegrandson&gt;<br />&nbsp;&nbsp;&nbsp; son&gt;<br />root&gt;<br />最佳使用类似XMLSPY这样的工具打开，因为这些工具能自动整理xml文件的栅格，否则非常有可能是没有所有换行的一个xml文件，可读性较差。<br />3.2&nbsp;&nbsp;&nbsp;解析xml文件<br />解析一个xml文件，从中取出想要的信息，例如节点中包含的文字，或某个节点的属性，其流程如下：<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用xmlReadFile函数读出一个文件指针doc；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用xmlDocGetRootElement函数得到根节点curNode；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curNode-&gt;xmlChildrenNode就是根节点的子节点集合；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;轮询子节点集合，找到所需的节点，用xmlNodeGetContent取出其内容；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用xmlHasProp查找含有某个属性的节点；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;取出该节点的属性集合，用xmlGetProp取出其属性值；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用xmlFreeDoc函数关闭文件指针，并清除本文件中所有节点动态申请的内存。<br />注意：节点列表的指针依然是xmlNodePtr，属性列表的指针也是xmlAttrPtr，并没有xmlNodeList或xmlAttrList这样的类型。看作列表的时候使用他们的next和prev链表指针来进行轮询。只有在Xpath中有xmlNodeSet这种类型，其使用方法前面已介绍了。<br />原始码如下：ParseXmlFile.cpp<br />/********************************************************************<br />&nbsp;&nbsp;&nbsp; created:&nbsp;&nbsp; 2007/11/15<br />&nbsp;&nbsp;&nbsp; created:&nbsp;&nbsp; 15:11:2007&nbsp;&nbsp; 11:47<br />&nbsp;&nbsp;&nbsp; filename: ParseXmlFile.cpp<br />&nbsp;&nbsp;&nbsp; author:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Wang xuebin&nbsp;<br />&nbsp;&nbsp;&nbsp; depend:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; libxml2.lib<br />&nbsp;&nbsp;&nbsp; build:&nbsp;&nbsp;&nbsp;&nbsp; nmake TARGET_NAME=ParseXmlFile<br />&nbsp;&nbsp;&nbsp; purpose:&nbsp;&nbsp;&nbsp;解析xml文件<br />*********************************************************************/<br />#include&nbsp;<br />#include&nbsp;<br />int main(int argc, char* argv[])<br />{<br />&nbsp;&nbsp;&nbsp; xmlDocPtr doc;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //定义解析文件指针<br />&nbsp;&nbsp;&nbsp; xmlNodePtr curNode;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //定义结点指针(你需要他为了在各个结点间移动)&nbsp;<br />&nbsp;&nbsp;&nbsp; xmlChar *szKey;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //临时字符串变量<br />&nbsp;&nbsp;&nbsp; char *szDocName;<br />&nbsp;&nbsp;&nbsp; if (argc&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("Usage: %s docname"n", argv[0]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return(0);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; szDocName = argv[1];<br />&nbsp;&nbsp;&nbsp; doc = xmlReadFile(szDocName,"GB2312",XML_PARSE_RECOVER); //解析文件<br />&nbsp;&nbsp;&nbsp; //检查解析文件是否成功，如果不成功，libxml将指一个注册的错误并停止。<br />&nbsp;&nbsp;&nbsp; //一个常见错误是不适当的编码。XML标准文件除了用UTF-8或UTF-16外还可用其他编码保存。<br />&nbsp;&nbsp;&nbsp; //如果文件是这样，libxml将自动地为你转换到UTF-8。更多关于XML编码信息包含在XML标准中.<br />&nbsp;&nbsp;&nbsp; if (NULL == doc)&nbsp;<br />&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fprintf(stderr,"Document not parsed successfully. "n");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;&nbsp;<br />&nbsp;&nbsp;&nbsp; }&nbsp;<br />&nbsp;&nbsp;&nbsp; curNode = xmlDocGetRootElement(doc); //确定文件根元素<br />&nbsp;&nbsp;&nbsp; /*检查确认当前文件中包含内容*/&nbsp;<br />&nbsp;&nbsp;&nbsp; if (NULL == curNode)<br />&nbsp;&nbsp;&nbsp; {&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fprintf(stderr,"empty document"n");&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlFreeDoc(doc);&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;&nbsp;<br />&nbsp;&nbsp;&nbsp; }&nbsp;<br />&nbsp;&nbsp;&nbsp; /*在这个例子中，我们需要确认文件是正确的类型。&ldquo;root&rdquo;是在这个示例中使用文件的根类型。*/<br />&nbsp;&nbsp;&nbsp; if (xmlStrcmp(curNode-&gt;name, BAD_CAST "root"))&nbsp;<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fprintf(stderr,"document of the wrong type, root node != root");&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlFreeDoc(doc);&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;&nbsp;<br />&nbsp;&nbsp;&nbsp; }&nbsp;<br />&nbsp;&nbsp;&nbsp; curNode = curNode-&gt;xmlChildrenNode;<br />&nbsp;&nbsp;&nbsp; xmlNodePtr propNodePtr = curNode;<br />&nbsp;&nbsp;&nbsp; while(curNode != NULL)&nbsp;<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //取出节点中的内容<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((!xmlStrcmp(curNode-&gt;name, (const xmlChar *)"newNode1")))&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; szKey = xmlNodeGetContent(curNode);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("newNode1: %s"n", szKey);&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlFree(szKey);&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //查找带有属性attribute的节点<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (xmlHasProp(curNode,BAD_CAST "attribute"))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; propNodePtr = curNode;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curNode = curNode-&gt;next;&nbsp;<br />&nbsp;&nbsp;&nbsp; }&nbsp;<br />&nbsp;&nbsp;&nbsp; //查找属性<br />&nbsp;&nbsp;&nbsp; xmlAttrPtr attrPtr = propNodePtr-&gt;properties;<br />&nbsp;&nbsp;&nbsp; while (attrPtr != NULL)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!xmlStrcmp(attrPtr-&gt;name, BAD_CAST "attribute"))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlChar* szAttr = xmlGetProp(propNodePtr,BAD_CAST "attribute");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlFree(szAttr);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; attrPtr = attrPtr-&gt;next;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; xmlFreeDoc(doc);<br />&nbsp;&nbsp;&nbsp; return 0;<br />}<br />编译链接命令如下：<br />nmake TARGET_NAME=ParseXmlFile<br />执行命令如下，使用第一次创建的xml文件作为输入：<br />ParseXmlFile.exe CreatedXml.xml<br />观察原始码可发现，所有以查询方式得到的xmlChar*字符串都必须使用xmlFree函数手动释放。否则会造成内存泄漏。<br />3.3&nbsp;&nbsp;&nbsp;修改xml文件<br />有了上面的基础，修改xml文件的内容就非常简单了。首先打开一个已存在的xml文件，顺着根结点找到需要添加、删除、修改的地方，调用相应的xml函数对节点进行增、删、改操作。原始码见ChangeXmlFile，编译链接方法如上。执行下面的命令：<br />ChangeXmlFile.exe CreatedXml.xml<br />能得到一个修改后的xml文件ChangedXml.xml，如下：<br />root&gt;<br />&nbsp;&nbsp;&nbsp; newNode2&gt;content changednewNode2&gt;<br />&nbsp;&nbsp;&nbsp; newNode3 newAttr="YES"&gt;newNode3 contentnewNode3&gt;<br />&nbsp;&nbsp;&nbsp; node2 attribute="no"&gt;NODE CONTENTnode2&gt;<br />&nbsp;&nbsp;&nbsp; son&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; grandson&gt;This is a grandson nodegrandson&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newGrandSon&gt;new contentnewGrandSon&gt;<br />&nbsp;&nbsp;&nbsp; son&gt;<br />root&gt;<br />需要注意的是，并没有xmlDelNode或xmlRemoveNode函数，我们删除节点使用的是以下一段代码：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!xmlStrcmp(curNode-&gt;name, BAD_CAST "newNode1"))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlNodePtr tempNode;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tempNode = curNode-&gt;next;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlUnlinkNode(curNode);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlFreeNode(curNode);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curNode = tempNode;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />即将当前节点从文件中断链（unlink），这样本文件就不会再包含这个子节点。这样做需要使用一个临时变量来存储断链节点的后续节点，并记得要手动删除断链节点的内存。<br />3.4&nbsp;&nbsp;&nbsp;使用XPATH查找xml文件<br />简而言之，XPATH之于xml，好比SQL之于关系数据库。要在一个复杂的xml文件中查找所需的信息，XPATH简直是必不可少的工具。XPATH语法简单易学，并且有一个非常好的官方教程，见<br /><a href="http://www.zvon.org/xxl/XPathTutorial/Output_chi/introduction.html"><span>http://www.zvon.org/xxl/XPathTutorial/Output_chi/introduction.html</span></a><br />。这个站点的XML各种教程齐全，并且有包括中文在内的各国语言版本，真是让我喜欢到非常！<br />使用XPATH之前，必须首先熟悉几个数据类型和函数，他们是使用XPATH的前提。在<em><a href="http://blog.csdn.net/shanzhizi" target="_blank">libxml2</a></em>中使用Xpath是非常简单的，其流程如下：<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;定义一个XPATH上下文指针xmlXPathContextPtr context，并且使用xmlXPathNewContext函数来初始化这个指针；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;定义一个XPATH对象指针xmlXPathObjectPtr result，并且使用xmlXPathEvalExpression函数来计算Xpath表达式，得到查询结果，将结果存入对象指针中；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;使用result-&gt;nodesetval得到节点集合指针，其中包含了所有符合Xpath查询结果的节点；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;使用xmlXPathFreeContext释放上下文指针；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;使用xmlXPathFreeObject释放Xpath对象指针；<br />具体的使用方法能看XpathForXmlFile.cpp的这一段代码，其功能是查找符合某个Xpath语句的对象指针：<br />xmlXPathObjectPtr getNodeSet(xmlDocPtr doc, const xmlChar *szXpath)&nbsp;<br />{<br />&nbsp;&nbsp;&nbsp; xmlXPathContextPtr context;&nbsp;&nbsp;&nbsp; //XPATH上下文指针<br />&nbsp;&nbsp;&nbsp; xmlXPathObjectPtr result;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //XPATH对象指针，用来存储查询结果<br />&nbsp;&nbsp;&nbsp; context = xmlXPathNewContext(doc);&nbsp;&nbsp;&nbsp;&nbsp; //创建一个XPath上下文指针<br />&nbsp;&nbsp;&nbsp; if (context == NULL)&nbsp;<br />&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("context is NULL"n");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return NULL;&nbsp;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; result = xmlXPathEvalExpression(szXpath, context); //查询XPath表达式，得到一个查询结果<br />&nbsp;&nbsp;&nbsp; xmlXPathFreeContext(context);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //释放上下文指针<br />&nbsp;&nbsp;&nbsp; if (result == NULL)&nbsp;<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("xmlXPathEvalExpression return NULL"n");&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return NULL;&nbsp;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; if (xmlXPathNodeSetIsEmpty(result-&gt;nodesetval))&nbsp;&nbsp; //检查查询结果是否为空<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlXPathFreeObject(result);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("nodeset is empty"n");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return NULL;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; return result;&nbsp;&nbsp;&nbsp;&nbsp;<br />}<br />一个完整的使用Xpath的例子在代码XpathForXmlFile.cpp中，他查找一个xml文件中符合"/root/node2[@attribute=&rsquo;yes&rsquo;]"语句的结果，并且将找到的节点的属性和内容打印出来。编译链接命令如下：<br />nmake TARGET_NAME=XpathForXmlFile<br />执行方式如下：<br />XpathForXmlFile.exe CreatedXml.xml<br />观察结果能看出找到了一个节点，即root下面node2节点，他的attribute属性值正好等于yes。更多关于Xpath的内容能参考XPATH官方手册。只有掌控了XPATH，才掌控了使用大型XML文件的方法，否则每寻找一个节点都要从根节点找起，会把人累死。<br />4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用ICONV解决XML中的中文问题<br />Libxml2中默认的内码是UTF-8，所有使用libxml2进行处理的xml文件，必须首先显式或默认的转换为UTF-8编码才能被处理。<br />要在xml中使用中文，就必须能够在UTF-8和GB2312内码（较常用的一种简体中文编码）之间进行转换。Libxml2提供了默认的内码转换机制，并且在libxml2的Tutorial中有一个例子，事实证实这个例子并不适合用来转换中文。<br />所以需要我们显式的使用ICONV来进行内码转换，libxml2本身也是使用ICONV进行转换的。ICONV是个专门用来进行编码转换的库，基本上支持目前所有常用的编码。他是glibc库的一个部分，常常被用于UNIX系统中。当然，在windows下面使用也没有所有问题。前面已提到了ICONV的安装和使用方法，这里主要讲一下编程相关问题。<br />本节其实和xml及libxml2没有太大关系，你能把他简单看作是个编码转换方面的专题。我们仅仅需要学会使用两个函数就能了，即从UTF-8转换到GB2312的函数u2g，及反向转换的函数g2u，原始码在wxb_codeConv.c中：<br />/********************************************************************<br />&nbsp;&nbsp;&nbsp; created:&nbsp;&nbsp; 2007/11/15<br />&nbsp;&nbsp;&nbsp; created:&nbsp;&nbsp; 15:11:2007&nbsp;&nbsp; 10:30<br />&nbsp;&nbsp;&nbsp; filename: wxb_codeConv.c<br />&nbsp;&nbsp;&nbsp; author:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Wang xuebin&nbsp;<br />&nbsp;&nbsp;&nbsp; depend:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iconv.lib<br />&nbsp;&nbsp;&nbsp; build:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;不必build，被包含到其他原始码中<br />&nbsp;&nbsp;&nbsp; purpose:&nbsp;&nbsp;&nbsp;提供从UTF-8到GB2312的内码转换，及反向的转换<br />*********************************************************************/<br />#include "iconv.h"<br />#include&nbsp;<br />//代码转换:从一种编码转为另一种编码&nbsp;&nbsp;&nbsp;<br />int code_convert(char* from_charset, char* to_charset, char* inbuf,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int inlen, char* outbuf, int outlen)<br />{<br />&nbsp;&nbsp;&nbsp; iconv_t cd;<br />&nbsp;&nbsp;&nbsp; char** pin = &amp;inbuf;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; char** pout = &amp;outbuf;<br />&nbsp;&nbsp;&nbsp; cd = iconv_open(to_charset,from_charset);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; if(cd == 0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br />&nbsp;&nbsp;&nbsp; memset(outbuf,0,outlen);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; if(iconv(cd,(const char**)pin,(unsigned int *)&amp;inlen,pout,(unsigned int*)&amp;outlen)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; == -1)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; iconv_close(cd);<br />&nbsp;&nbsp;&nbsp; return 0;&nbsp;&nbsp;&nbsp;<br />}<br />//UNICODE码转为GB2312码&nbsp;&nbsp;&nbsp;<br />//成功则返回一个动态分配的char*变量，需要在使用完毕后手动free，失败返回NULL<br />char* u2g(char *inbuf)&nbsp;&nbsp;&nbsp;<br />{<br />&nbsp;&nbsp;&nbsp; int nOutLen = 2 * strlen(inbuf) - 1;<br />&nbsp;&nbsp;&nbsp; char* szOut = (char*)malloc(nOutLen);<br />&nbsp;&nbsp;&nbsp; if (-1 == code_convert("utf-8","gb2312",inbuf,strlen(inbuf),szOut,nOutLen))<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; free(szOut);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; szOut = NULL;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; return szOut;<br />}&nbsp;&nbsp;&nbsp;<br />//GB2312码转为UNICODE码&nbsp;&nbsp;&nbsp;<br />//成功则返回一个动态分配的char*变量，需要在使用完毕后手动free，失败返回NULL<br />char* g2u(char *inbuf)&nbsp;&nbsp;&nbsp;<br />{<br />&nbsp;&nbsp;&nbsp; int nOutLen = 2 * strlen(inbuf) - 1;<br />&nbsp;&nbsp;&nbsp; char* szOut = (char*)malloc(nOutLen);<br />&nbsp;&nbsp;&nbsp; if (-1 == code_convert("gb2312","utf-8",inbuf,strlen(inbuf),szOut,nOutLen))<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; free(szOut);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; szOut = NULL;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; return szOut;<br />}&nbsp;&nbsp;&nbsp;<br />使用的时候将这个c文件include到其他源文件中。include一个c文件并不奇怪，在c语言的年代我们常常这么干，唯一的害处的编译链接出来的可执行程式体积变大了。当然这时因为我们这段代码非常小的原因，再大一点我就要用dll了。<br />从UTF-8到GB2312的一个典型使用流程如下：<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;得到一个UTF-8的字符串szSrc；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;定义一个char*的字符指针szDes，并不必给他动态审判内存；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; szDes = u2g(szSrc)，这样就能得到转换后的GB2312编码的字符串；<br />l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;使用完这个字符串后使用free(szDes)来释放内存。<br />本文并不准备讲述iconv中的函数细节，因为那几个函数及数据类型都非常简单，我们还是重点看一下怎么在libxml2中使用编码转换来处理带有中文的xml文件。下面是使用以上方法来创建一个带有中文的XML文件的例子程式CreateXmlFile_cn.cpp，原始码如下：<br />/********************************************************************<br />&nbsp;&nbsp;&nbsp; created:&nbsp;&nbsp; 2007/11/17<br />&nbsp;&nbsp;&nbsp; created:&nbsp;&nbsp; 9:11:2007&nbsp;&nbsp; 15:34<br />&nbsp;&nbsp;&nbsp; filename: CreateXmlFile.cpp<br />&nbsp;&nbsp;&nbsp; author:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Wang xuebin&nbsp;<br />&nbsp;&nbsp;&nbsp; depend:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; libxml2.lib iconv.lib<br />&nbsp;&nbsp;&nbsp; build:&nbsp;&nbsp;&nbsp;&nbsp; nmake TARGET_NAME=CreateXmlFile_cn<br />&nbsp;&nbsp;&nbsp; purpose:&nbsp;&nbsp;&nbsp;创建一个xml文件，其中包含中文<br />*********************************************************************/<br />#include&nbsp;<br />#include&nbsp;<br />#include&nbsp;<br />#include&nbsp;<br />#include "wxb_codeConv.c" //自己写的编码转换函数<br />int main(int argc, char **argv)<br />{<br />&nbsp;&nbsp;&nbsp; //定义文件和节点指针<br />&nbsp;&nbsp;&nbsp; xmlDocPtr doc = xmlNewDoc(BAD_CAST"1.0");<br />&nbsp;&nbsp;&nbsp; xmlNodePtr root_node = xmlNewNode(NULL,BAD_CAST"root");<br />&nbsp;&nbsp;&nbsp; //设置根节点<br />&nbsp;&nbsp;&nbsp; xmlDocSetRootElement(doc,root_node);<br />&nbsp;&nbsp;&nbsp; //一个中文字符串转换为UTF-8字符串，然后写入<br />&nbsp;&nbsp;&nbsp; char* szOut = g2u("节点1的内容");<br />&nbsp;&nbsp;&nbsp; //在根节点中直接创建节点<br />&nbsp;&nbsp;&nbsp; xmlNewTextChild(root_node, NULL, BAD_CAST "newNode1", BAD_CAST "newNode1 content");<br />&nbsp;&nbsp;&nbsp; xmlNewTextChild(root_node, NULL, BAD_CAST "newNode2", BAD_CAST "newNode2 content");<br />&nbsp;&nbsp;&nbsp; xmlNewTextChild(root_node, NULL, BAD_CAST "newNode3", BAD_CAST "newNode3 content");<br />&nbsp;&nbsp;&nbsp; xmlNewChild(root_node, NULL, BAD_CAST "node1",BAD_CAST szOut);<br />&nbsp;&nbsp;&nbsp; free(szOut);<br />&nbsp;&nbsp;&nbsp; //创建一个节点，设置其内容和属性，然后加入根结点<br />&nbsp;&nbsp;&nbsp; xmlNodePtr node = xmlNewNode(NULL,BAD_CAST"node2");<br />&nbsp;&nbsp;&nbsp; xmlNodePtr content = xmlNewText(BAD_CAST"NODE CONTENT");<br />&nbsp;&nbsp;&nbsp; xmlAddChild(root_node,node);<br />&nbsp;&nbsp;&nbsp; xmlAddChild(node,content);<br />&nbsp;&nbsp;&nbsp; szOut = g2u("属性值");<br />&nbsp;&nbsp;&nbsp; xmlNewProp(node,BAD_CAST"attribute",BAD_CAST szOut);<br />&nbsp;&nbsp;&nbsp; free(szOut);<br />&nbsp;&nbsp;&nbsp; //创建一个中文节点<br />&nbsp;&nbsp;&nbsp; szOut = g2u("中文节点");<br />&nbsp;&nbsp;&nbsp; xmlNewChild(root_node, NULL, BAD_CAST szOut,BAD_CAST "content of chinese node");<br />&nbsp;&nbsp;&nbsp; free(szOut);<br />&nbsp;&nbsp;&nbsp; //存储xml文件<br />&nbsp;&nbsp;&nbsp; int nRel = xmlSaveFormatFileEnc("CreatedXml_cn.xml",doc,"GB2312",1);<br />&nbsp;&nbsp;&nbsp; if (nRel != -1)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout一个xml文件被创建,写入"个字节"&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; xmlFreeDoc(doc);<br />&nbsp;&nbsp;&nbsp; return 1;<br />}<br />编译链接命令如下：<br />nmake TARGET_NAME=CreateXmlFile_cn<br />完成后执行CreateXmlFile_cn.exe能生成一个xml文件CreatedXml_cn.xml，其内容如下：<br />root&gt;<br />&nbsp;&nbsp;&nbsp; newNode1&gt;newNode1 contentnewNode1&gt;<br />&nbsp;&nbsp;&nbsp; newNode2&gt;newNode2 contentnewNode2&gt;<br />&nbsp;&nbsp;&nbsp; newNode3&gt;newNode3 contentnewNode3&gt;<br />&nbsp;&nbsp;&nbsp; node1&gt;节点1的内容node1&gt;<br />&nbsp;&nbsp;&nbsp; node2 attribute="属性值"&gt;NODE CONTENTnode2&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;中文节点&gt;content of chinese node中文节点&gt;<br />root&gt;<br />观察可知，节点的名称、内容、属性都能使用中文了。在解析、修改和查找XML文件时都能使用上面的方法，只要记住，进入xml文件之前将中文编码转换为UTF-8编码；从XML中取出数据时，不管三七二十一都能转换为GB2312再用，否则你非常有可能见到传说中的乱码！<br />5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用XML来做点什么<br />有了以上的基础，相信已能顺利的在c/c++程式中使用XML文件了。那么，我们到底要用XML来做什么呢？我随便说一说自己的想法：<br />第一，能用来作为设置文件。例如非常多组件就是用XML来做设置文件；当然，我们知道用INI做设置文件更简单，只要熟悉两个函数就能了；不过，复杂一点的设置文件我还是建议采用XML；<br />第二，能用来作为在程式之间传送数据的格式，这样的话最佳给你的xml先定义一个XML Schema，这样的数据首先能做一个良构校验，还能来一个Schema校验，如此的话出错率会比没有格式的数据小得多。目前XML已广泛作为网络之间的数据格式了；<br />第三，能用来作为你自定义的数据存储格式，例如对象持久化之类的功能；<br />最后，能用来显示你的技术非常高深，本来你要存储一个1，结果你这样存储了：<br />root&gt;<br />&nbsp;&nbsp;&nbsp; My_Program_Code content="1"&gt;My_Program_Code&gt;<br />root&gt;</p></div><div id="MySignature"></div>
<div class="clear"></div>
<div id="blog_post_info_block">
<div id="BlogPostCategory"></div>
<div id="EntryTag"></div>
<div id="blog_post_info">
</div>
<div class="clear"></div>
<div id="post_next_prev"></div>
</div>


		</div>
		<div class = "postDesc">posted @ <span id="post-date">2012-07-09 22:02</span> <a href='http://www.cnblogs.com/shanzhizi/'>蹒跚</a> 阅读(<span id="post_view_count">...</span>) 评论(<span id="post_comment_count">...</span>)  <a href ="http://i.cnblogs.com/EditPosts.aspx?postid=2583739" rel="nofollow">编辑</a> <a href="#" onclick="AddToWz(2583739);return false;">收藏</a></div>
	</div>
	<script type="text/javascript">var allowComments=true,isLogined=false,cb_blogId=121698,cb_entryId=2583739,cb_blogApp=currentBlogApp,cb_blogUserGuid='7ac991c8-dfc5-e111-aa3f-842b2b196315',cb_entryCreatedDate='2012/7/9 22:02:00';loadViewCount(cb_entryId);</script>
	
</div><!--end: topics 文章、评论容器-->
<a name="!comments"></a><div id="blog-comments-placeholder"></div><script type="text/javascript">var commentManager = new blogCommentManager();commentManager.renderComments(0);</script>
<div id="comment_form" class="commentform">
<a name="commentform"></a>
<div id="divCommentShow"></div>
<div id="comment_nav"><span id="span_refresh_tips"></span><a href="javascript:void(0);" id="lnk_RefreshComments" onclick="return RefreshCommentList();">刷新评论</a><a href="#" onclick="return RefreshPage();">刷新页面</a><a href="#top">返回顶部</a></div>
<div id="comment_form_container"></div>
<div class="ad_text_commentbox" id="ad_text_under_commentbox"></div>
<div id="site_nav_under"><a href="http://www.cnblogs.com/" target="_blank" title="开发者的网上家园">博客园首页</a><a href="http://q.cnblogs.com/" target="_blank" title="程序员问答社区">博问</a><a href="http://news.cnblogs.com/" target="_blank" title="IT新闻">新闻</a><a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a><a href="http://job.cnblogs.com/" target="_blank">程序员招聘</a><a href="http://kb.cnblogs.com/" target="_blank">知识库</a></div>
<div id="opt_under_post"></div>
<script type="text/javascript">
    var enableGoogleAd = canShowAdsense(); var googletag = googletag || {}; googletag.cmd = googletag.cmd || [];
    fixPostBodyFormat();
</script>
<div id="ad_under_post_holder">
<script type='text/javascript'>
    var googletag = googletag || {};
    googletag.cmd = googletag.cmd || [];
    (function () {
        if (enableGoogleAd) {
            var gads = document.createElement('script');
            gads.async = true;
            gads.type = 'text/javascript';
            var useSSL = 'https:' == document.location.protocol;
            gads.src = (useSSL ? 'https:' : 'http:') + '//www.googletagservices.com/tag/js/gpt.js';
            var node = document.getElementsByTagName('script')[0];
            node.parentNode.insertBefore(gads, node);
        }
    })();
</script>
<script type='text/javascript'>
    try {
        if (enableGoogleAd) {
            googletag.cmd.push(function () {
                googletag.defineSlot('/1090369/cnblogs_blogpost_C1_sitehome', [300, 250], 'div-gpt-ad-1346480159711-0').addService(googletag.pubads());
                googletag.defineSlot('/1090369/cnblogs_blogpost_C2', [468, 60], 'div-gpt-ad-1410860226396-0').addService(googletag.pubads());
                googletag.pubads().enableSingleRequest();
                googletag.enableServices();
            });
        };
    } catch (e) { }
</script>
<div id="google_ad_c1" class="c_ad_block">
    <div id='div-gpt-ad-1346480159711-0' style='width:300px; height:250px;'>
    <script type='text/javascript'>
        try {
            if (enableGoogleAd) {
                googletag.cmd.push(function () { googletag.display('div-gpt-ad-1346480159711-0'); });            
            } else {
                $('#div-gpt-ad-1346480159711-0').hide();
            }
    } catch (e) { }
    </script>
    </div>
</div>
</div>
<div id="under_post_news"></div>
<div id="google_ad_c2" class="c_ad_block">
<div id='div-gpt-ad-1410860226396-0' style='width:468px; height:60px;'>
<script type='text/javascript'>
try {
    if (enableGoogleAd) {
        googletag.cmd.push(function () { googletag.display('div-gpt-ad-1410860226396-0'); });
    } else {
        $('#div-gpt-ad-1346480159711-0').hide();
    }
} catch (e) { }
</script>
</div>
</div>
<div id="under_post_kb"></div>
<div id="HistoryToday" class="c_ad_block"></div>
<script type="text/javascript">
$(function () {
    loadNewsAndKb();
    loadBlogSignature();
    LoadPostInfoBlock(cb_blogId, cb_entryId, cb_blogApp, cb_blogUserGuid);
    GetPrevNextPost(cb_entryId, cb_blogId, cb_entryCreatedDate);
    loadOptUnderPost();
    GetHistoryToday(cb_blogId, cb_blogApp, cb_entryCreatedDate);
    setTimeout(function () { incrementViewCount(cb_entryId); }, 200);
});
</script>
</div>

	</div><!--end: forFlow -->
	</div><!--end: mainContent 主体内容容器-->

	<div id="sideBar">
		<div id="sideBarMain">
			
			<div id="calendar"><div id="blog-calendar" style="display:none"></div><script type="text/javascript">loadBlogDefaultCalendar();</script></div>
			
			<div id="leftcontentcontainer">
				<div id="blog-sidecolumn"></div><script type="text/javascript">loadBlogSideColumn();</script>
			</div>
			
		</div><!--end: sideBarMain -->
	</div><!--end: sideBar 侧边栏容器 -->
	<div class="clear"></div>
	</div><!--end: main -->
	<div class="clear"></div>
	<div id="footer">
		
<!--done-->
Copyright &copy;2015 蹒跚
	</div><!--end: footer -->
</div><!--end: home 自定义的最大容器 -->
</body>
</html>
